1 /*
2 Copyright: Marcelo S. N. Mancini (Hipreme|MrcSnm), 2018 - 2021
3 License:   [https://creativecommons.org/licenses/by/4.0/|CC BY-4.0 License].
4 Authors: Marcelo S. N. Mancini
5 
6 	Copyright Marcelo S. N. Mancini 2018 - 2021.
7 Distributed under the CC BY-4.0 License.
8    (See accompanying file LICENSE.txt or copy at
9 	https://creativecommons.org/licenses/by/4.0/
10 */
11 
12 module hip.api.input.gamepad;
13 
14 public import hip.api.input.button;
15 
16 enum HipGamepadAnalogs : ubyte
17 {
18     leftStick,
19     rightStick,
20     leftTrigger,
21     rightTrigger
22 }
23 
24 /** Define order is starting from up and it goes counter clockwise*/
25 enum HipGamepadButton : ubyte
26 {
27     dPadUp = 0,
28     dPadLeft,
29     dPadDown,
30     dPadRight,
31 
32     psTriangle,
33     psSquare,
34     psCross,
35     psCircle,
36 
37     xboxY = psTriangle,
38     xboxX = psSquare,
39     xboxA = psCross,
40     xboxB = psCircle,
41 
42     left1,
43     right1,
44 
45     left2,
46     right2,
47 
48     left3,
49     right3,
50 
51     start,
52     select,
53     home,
54     printScreen,
55     volumeUp,
56     volumeDown,
57 
58     ///Internal usage only
59     count
60 }
61 
62 
63 HipGamepadButton gamepadButtonFromString(string str)
64 {
65     switch(str)
66     {
67         static foreach(btn; __traits(allMembers, HipGamepadButton))
68         {
69             case btn:
70                 return __traits(getMember, HipGamepadButton, btn);
71         }
72         default:
73             return HipGamepadButton.count;
74     }
75 }
76 
77 ///Based on https://docs.microsoft.com/en-us/uwp/api/windows.system.power.batterystatus?view=winrt-20348
78 enum HipGamepadBatteryState : ubyte
79 {
80     notPresent = 0,
81     discharging,
82     idle,
83     charging,
84 }
85 ///Struct based on winrt::Windows::Devices::Power::BatteryReport
86 struct HipGamepadBatteryStatus
87 {
88     int chargeRateInMilliwatts;
89     int remainingCapacityInMilliwattHours;
90     int fullChargeCapacityInMilliwattHours;
91     HipGamepadBatteryState state;
92 }
93 
94 interface IHipGamepad
95 {
96     /** Returns wether it is vibrating. Receives a time to stop vibrating */
97     bool setVibrating(float vibrationPower, float time = 0.5);
98     bool isVibrating();
99     /** Returns the Id for this controller, usually the order in which it was connected*/
100     ubyte getId();
101 
102     /** Completely implementation dependent, 
103     *   deltaTime is used for it auto stop vibrating
104     */
105     void poll(float deltaTime);
106 
107     /** Returns a Vector3 containing the current state of the analog */
108     float[3] getAnalogState(HipGamepadAnalogs analog = HipGamepadAnalogs.leftStick);
109     /** This will set a deadzone for making gamepad doesn't issue any kind of event until the threshold*/
110     void setDeadzone(float threshold = 0.1);
111 
112     /** Returns the battery status in range 0 - 1, only makes sense when wireless*/
113     float getBatteryStatus()out(r; (r > 0.0f && r <= 1.0f), "Battery should be 0 > battery <= 1");
114     /** Knowing wether it is wireless may be essential for showing battery alert */
115     bool isWireless();
116 
117 
118     /** Receives a gamepad button*/
119     bool isButtonPressed(HipGamepadButton btn);
120     bool isButtonJustPressed(HipGamepadButton btn);
121     bool isButtonJustReleased(HipGamepadButton btn);
122 
123     final bool isButtonPressed(string btn){return isButtonPressed(gamepadButtonFromString(btn));}
124     /** After first created, gamepads are never destroyed, use this property for using it or not*/
125     bool isConnected();
126 
127     /** May include an implementation for turning gamepad off*/
128     void setConnected(bool connected);
129 
130 
131 }
132 
133 abstract class AHipGamepad : IHipGamepad
134 {
135     protected float vibrationPower = 0;
136     protected float vibrationTime = 0;
137     protected bool _isConnected = false;
138     protected float deadZone = 0.1;
139     protected float aliveZone = 0.95;
140 
141     void setDeadzone(float threshold = 0.1){deadZone = threshold;}
142     void setAlivezone(float threshold = 0.95){aliveZone = threshold;}
143     bool isVibrating(){return vibrationPower==0;}
144     bool isConnected(){return _isConnected;}
145     void setConnected(bool connected){_isConnected = connected;}
146 
147 }